﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Table_Dal;
namespace ApplicationLayer
{
    public class GiaiThuatGen
    {
        private List<CauHoi_GiaiThuatTbl> lstQuanThe;
        public GiaiThuatGen() {
            lstQuanThe = new List<CauHoi_GiaiThuatTbl>();
        }
        public GiaiThuatGen(List<CauHoi_GiaiThuatTbl> lst)
        {
            lstQuanThe = new List<CauHoi_GiaiThuatTbl>();
            lstQuanThe = lst;
        }
        Random random0 = new Random();
        #region khoi tao quan the [DanhSachDeThi]
        public List<DeThi_GiaiThuatTbl> DanhSachDeThi(int sodethi, int socauhoi, List<CauHoi_GiaiThuatTbl> lstQuanThe)
        {
            //Khoi Tao Quan The
            List<DeThi_GiaiThuatTbl> dsDeThi = new List<DeThi_GiaiThuatTbl>();
            for (int j = 0; j < sodethi; j++)
            {
                dsDeThi.Add(TaoDeThi(j, lstQuanThe, socauhoi));
            }
            return dsDeThi;
        }
        #endregion

        #region Tao cac ca' the ban dau [TaoDeThi]
        private DeThi_GiaiThuatTbl TaoDeThi(int made, List<CauHoi_GiaiThuatTbl> lstQuanThe, int socauhoi)
        {
            DeThi_GiaiThuatTbl dethimoi = new DeThi_GiaiThuatTbl();
            dethimoi.MADETHI = made.ToString();
            dethimoi.TENDETHI = "Đề " + (made + 1).ToString();
            dethimoi.SOCAUHOI = socauhoi;
            for (int i = 0; i < socauhoi; i++)
            {
                bool flag = true;
                int stt_cauhoi = 0;
                while (flag == true)
                {
                    flag = false;
                    stt_cauhoi = random0.Next(0, lstQuanThe.Count - 1);
                    foreach (CauHoi_GiaiThuatTbl item in dethimoi.lstCauHoi)
                    {
                        if (item.MaCauHoi.Equals(lstQuanThe[stt_cauhoi].MaCauHoi))
                        {
                            flag = true;
                            break;
                        }
                    }
                }
                dethimoi.lstCauHoi.Add(lstQuanThe[stt_cauhoi]);
            }
            return dethimoi;
        }
        #endregion

        #region DoThichNghi [DoThichNghi]
        internal List<DeThi_GiaiThuatTbl> DoThichNghi(List<DeThi_GiaiThuatTbl> dsDeThi, List<Chuong_GiaiThuatTbl> ArrChuong_GT, YeuCauDeThi_GiaiThuatTbl DeThi_GT)
        {
            int thoigian;
            float dokho;
            double dothichnghi;
            float kienthuc = 0;
            float[] doKhoDethi = new float[5];
            int index = 0;
            int socau = 0;
            foreach (DeThi_GiaiThuatTbl Dethi in dsDeThi)
            {
                thoigian = 0;
                dokho = 0;
                index=0;
                bool TinhDoKho = true;
                for (int i = 0; i < 5; i++)
			    {
                    doKhoDethi[i] = 0;
                }
                kienthuc = 0;
                foreach (Chuong_GiaiThuatTbl chuong in ArrChuong_GT)
                {
                    socau = 0;
                    foreach (CauHoi_GiaiThuatTbl cauhoi in Dethi.lstCauHoi)
                    {
                        if (cauhoi.MaChuong == chuong.MaChuong)
                        {
                            thoigian += cauhoi.ThoiGian;
                            socau++;
                        }
                        if (TinhDoKho)
                        {
                            if (cauhoi.DoKho == 1) // Rat de
                                doKhoDethi[0]++;
                            if (cauhoi.DoKho == 2) // De
                                doKhoDethi[1]++;
                            if (cauhoi.DoKho == 3) // Vua
                                doKhoDethi[2]++;
                            if (cauhoi.DoKho == 4) // Kho
                                doKhoDethi[3]++;
                            if (cauhoi.DoKho == 5) // Rat kho
                                doKhoDethi[4]++;
                        }
                        
                    }
                    kienthuc += Math.Abs(((socau * 100) / DeThi_GT.SoCauHoi) - chuong.DoKho);
                    TinhDoKho = false;
                    index++;
                }
                dokho += Math.Abs(((doKhoDethi[0] * 100) / DeThi_GT.SoCauHoi) - DeThi_GT.RatDe);
                dokho += Math.Abs(((doKhoDethi[1] * 100) / DeThi_GT.SoCauHoi) - DeThi_GT.De);
                dokho += Math.Abs(((doKhoDethi[2] * 100) / DeThi_GT.SoCauHoi) - DeThi_GT.Vua);
                dokho += Math.Abs(((doKhoDethi[3] * 100) / DeThi_GT.SoCauHoi) - DeThi_GT.Kho);
                dokho += Math.Abs(((doKhoDethi[4] * 100) / DeThi_GT.SoCauHoi) - DeThi_GT.RatKho);
                Dethi.THOIGIAN = thoigian;
                thoigian = Math.Abs(thoigian - DeThi_GT.ThoiGian);
                thoigian = Math.Abs(thoigian * 100 / DeThi_GT.ThoiGian);
                dothichnghi = (double)(Math.Exp(kienthuc/100)*Math.Exp(dokho/100)*Math.Exp(thoigian/100));
                Dethi.DoThichNghi = -Math.Round(dothichnghi, 2);
            }
            return dsDeThi;
        }
        #endregion

        #region GhepCap [GhepCap]
        public List<GhepCapDeThi_GiaiThuatTbl> GhepCap(List<DeThi_GiaiThuatTbl> dsDeThi)
        {
            List<GhepCapDeThi_GiaiThuatTbl> lstGepCap = new List<GhepCapDeThi_GiaiThuatTbl>();
            List<DeThi_GiaiThuatTbl> ds = new List<DeThi_GiaiThuatTbl>();
            foreach (DeThi_GiaiThuatTbl dethi in dsDeThi)
            {
                ds.Add(dethi);
            }
            int socau, de1, de2;
            for (int i = 0; i < dsDeThi.Count/2; i++)
            {
                do
                {
                    socau = ds.Count();
                    de1 = random0.Next(socau);
                    de2 = random0.Next(socau);
                } while (de1 == de2 && socau > 1 && ds[de1].MADETHI == ds[de2].MADETHI);
                lstGepCap.Add(new GhepCapDeThi_GiaiThuatTbl(ds[de1], ds[de2]));
                ds.RemoveAt(de1);
                if (de1 < de2)
                    ds.RemoveAt(de2 - 1);
                else ds.RemoveAt(de2); 
            }
            return lstGepCap;
        }
        #endregion

        #region Lai Ghep [LaiGhep]
        public List<DeThi_GiaiThuatTbl> LaiGhep(List<GhepCapDeThi_GiaiThuatTbl> lstGepcap)
        {
            List<DeThi_GiaiThuatTbl> dsDe = new List<DeThi_GiaiThuatTbl>();
            int index;
            bool flag = true;
            int socau = lstGepcap[0].dethi1.lstCauHoi.Count; ;
            int Made = -1;
            List<CauHoi_GiaiThuatTbl>  dsChde1, dsChde2;
            foreach (GhepCapDeThi_GiaiThuatTbl CapDeThi in lstGepcap)
            {
                dsChde1= CapDeThi.dethi1.lstCauHoi;
                dsChde2 = CapDeThi.dethi2.lstCauHoi;
                index = random0.Next(1, socau - 1);
                for (int i = index; i < socau; i++)
                {
                    flag = true;
                    for (int j = 0; j < index; j++)
                        if (dsChde1[i].MaCauHoi == dsChde2[j].MaCauHoi || dsChde1[j].MaCauHoi == dsChde2[i].MaCauHoi)
                        {
                            flag = false;
                            break;
                        }
                    if (flag)
                    {
                        CauHoi_GiaiThuatTbl cauhoi = new CauHoi_GiaiThuatTbl();
                        cauhoi.MaCauHoi = dsChde1[i].MaCauHoi;
                        cauhoi.NoiDung = dsChde1[i].NoiDung;
                        cauhoi.DoKho = dsChde1[i].DoKho;
                        cauhoi.MaChuong = dsChde1[i].MaChuong;
                        cauhoi.ThoiGian = dsChde1[i].ThoiGian;
                        //dsChde1[i] = dsChde2[i];
                        dsChde1[i].MaCauHoi = dsChde2[i].MaCauHoi;
                        dsChde1[i].NoiDung = dsChde2[i].NoiDung;
                        dsChde1[i].DoKho = dsChde2[i].DoKho;
                        dsChde1[i].MaChuong = dsChde2[i].MaChuong;
                        dsChde1[i].ThoiGian = dsChde2[i].ThoiGian;
                        //dsChde2[i] = cauhoi;
                        dsChde2[i].MaCauHoi = cauhoi.MaCauHoi;
                        dsChde2[i].NoiDung = cauhoi.NoiDung;
                        dsChde2[i].DoKho = cauhoi.DoKho;
                        dsChde2[i].MaChuong = cauhoi.MaChuong;
                        dsChde2[i].ThoiGian = cauhoi.ThoiGian;
                    }
                }
                Made++;
                dsDe.Add(new DeThi_GiaiThuatTbl((Made).ToString(), "Đề " + (Made + 1).ToString(),socau,dsChde1));
                Made++;
                dsDe.Add(new DeThi_GiaiThuatTbl((Made).ToString(), "Đề " + (Made + 1).ToString(),socau,dsChde2));
            }    
            return dsDe;
        }
        #endregion

        #region DotBien [DotBien]
        internal List<DeThi_GiaiThuatTbl> DotBien(List<DeThi_GiaiThuatTbl> dsDeThi, float TiLeDotBien)
        {
            bool flag;
            foreach (DeThi_GiaiThuatTbl dethi in dsDeThi)
            {
                flag = true;
                float dotbien = random0.Next(1000) / 1000;
                if (dotbien < TiLeDotBien)
                {
                    int vitri = random0.Next(dethi.SOCAUHOI);
                    int thaythe;
                    do
                    {
                        thaythe = random0.Next(lstQuanThe.Count);
                        foreach (CauHoi_GiaiThuatTbl cauhoi in dethi.lstCauHoi)
                        {
                            if (cauhoi.MaChuong == lstQuanThe[thaythe].MaChuong)
                            {
                                flag = false;
                                break;
                            }
                        }
                    }
                    while (flag == false);
                    dethi.lstCauHoi[vitri] = lstQuanThe[thaythe];
                }
            }
            return dsDeThi;
        }
        #endregion

        #region GiaiThuatGen voi n vonglap [giaithuat]
        public List<DeThi_GiaiThuatTbl> giaithuat(List<DeThi_GiaiThuatTbl> dsDethi)
        {
            List<DeThi_GiaiThuatTbl> ds = new List<DeThi_GiaiThuatTbl>();
            List<GhepCapDeThi_GiaiThuatTbl> dsCap = new List<GhepCapDeThi_GiaiThuatTbl>();
            dsCap = GhepCap(dsDethi);
            ds = LaiGhep(dsCap);
            float TiLeDotBien = random0.Next(50) / 1000;
            ds = DotBien(ds,TiLeDotBien);
            return ds;
        }
        #endregion


    }
}
